home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
asm
/
alib11b.zip
/
CODE1.ZIP
/
DISPGRAP
/
FONTEDIT.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-09-13
|
58KB
|
1,315 lines
;----------------------------------------------------------------------
; Fontedit - Loads the current screen font and lets you modify it.
; Saves font in a COM file with integral loader. Requires EGA or VGA.
; Syntax: FONTEDIT [filespec]
; PC Magazine September 13, 1988
;----------------------------------------------------------------------
_TEXT SEGMENT PUBLIC 'CODE'
ASSUME CS:_TEXT,DS:_TEXT
ASSUME ES:_TEXT,SS:_TEXT
ORG 100H
START: JMP MAIN
; DATA AREA
; ---------
DB CR,SPACE,SPACE,SPACE,CR,LF
COPYRIGHT DB "FONTEDIT 1.0 (C) 1988 Ziff Communications Co. ",BOX
PROGRAMMER1 DB " PC Magazine ",BOX," Michael J. Mefford",0,CTRL_Z
CR EQU 13
LF EQU 10
CTRL_Z EQU 26
SPACE EQU 32
BOX EQU 254
ESC_SCAN EQU 1
ENTER_SCAN EQU 1CH
UP_ARROW EQU 48H
DN_ARROW EQU 50H
LEFT_ARROW EQU 4BH
RIGHT_ARROW EQU 4DH
Y_SCAN EQU 15H
BS_SCAN EQU 0EH
TAB_CHAR EQU 9
MAX_POINTS EQU 16
PIXEL_OFF EQU 177
PIXEL_ON EQU 219
EDIT_COL EQU 32
EDIT_ROW EQU 8
EDIT_TOP EQU EDIT_ROW SHL 8 + EDIT_COL
TEMPLATE_TOP EQU EDIT_TOP - 28
CHAR_TOP EQU EDIT_TOP + 28
BOX_TOP EQU EDIT_TOP + 1 - 400H
INTENSITY EQU 1000B
MICKEY EQU 20
BUTTONS LABEL WORD
LEFT_BUTTON DB 0
RIGHT_BUTTON DB 0
SHIFT_KEYS EQU 3
SHIFT_STATE DB ?
HORIZONTAL DW 0
VERTICAL DW 0
NORMAL EQU 07H
ATTRIBUTE DB 07H
INVERSE DB 70H
ROWS DB ?
MAX_LINES DW 16
MOUSE_FLAG DB 0
MODIFY_FLAG DB 0
BLANKS DB 0,32,255
FILE_FLAG DB 0
FILE_HANDLE DW ?
FILENAME DW ?
LAST_PIXEL DB ?
;format: reg,value SEQUENCER REGISTERS GRAPHICS CONTROLLER REGISTERS
; MAP MASK MEMORY MODE MODE REG MISC READ MAP SELECT
ACCESS_A000H DB 2,4, 4,7, 5,0, 6,4, 4,2
PROTECT_A000H DB 2,3, 4,3, 5,10H, 6,0AH, 4,0
MENU LABEL BYTE
DB "F1 Del row F2 Ins row F3 Dup row F4 Save $"
MENU1 LABEL BYTE
DB "F5 Copy template char. Tab = select edit/char box"
DB " Use: arrow keys or mouse",CR,LF
DB "Hold Shift key or mouse button to drag. Esc to exit"
DB " Rows displayed = ",CR,LF
DB "Left button = pixel on",CR,LF
DB "Right button = pixel off",CR,LF
DB "Space bar = toggle pixel$"
MENU2 LABEL BYTE
DB "Enter = select char.",0
DB "Button = select char.",0
DB "PgUp/PgDn prev./next char.",0
CAPTIONS DW TEMPLATE_TOP - 2
DB "Template Char",0
DW EDIT_TOP - 2
DB " Edit Char",0
DW CHAR_TOP - 2
DB "Character Set",0
CURRENT_BOX DB 218, 5 DUP (196), 194, 5 DUP (196), 191
DB 179, 5 DUP (SPACE), 179, 5 DUP (SPACE), 179
DB 192, 5 DUP (196), 193, 5 DUP (196), 217
NOT_ENOUGH DB "Not enough memory$"
NOT_SUPPORTED DB "Font too tall$"
NOT_EGA_VGA DB "Ega/Vga not found$"
SAVE_MSG DB CR,LF,"Save ",0
FILE_MSG DB "file",0
CREATE_MSG DB CR,LF,"Create ",0
EXIST_MSG DB CR,LF,"Write over existing ",0
YES_NO DB "? Y/N",0
FAILED_MSG DB CR,LF,"Failed$"
FILENAME_MSG DB CR,LF,"Enter filename",CR,LF,"$"
NOT_FONT_MSG DB " not font$"
COM DB ".COM",0
WARNING_MSG DB LF,"Warning! The cursor row will be deleted in"
DB " EVERY character in this font.",CR,LF,"Continue$"
DISPATCH_KEY DB 1, 4BH, 4DH, 48H, 50H, 49H
DB 51H, 0FH, 39H, 1CH, 3BH, 53H
DB 3CH, 52H, 3DH, 3EH, 3FH
DISPATCH_CNT EQU $ - DISPATCH_KEY
DISPATCH_TABLE DW EXIT, LEFT, RIGHT, UP, DOWN, PGUP
DW PGDN, TAB, SPACE_BAR, ENTER, DEL_ROW, DEL_ROW
DW INS_ROW, INS_ROW, DUP_ROW, SAVE, COPY_TEMP
DISPATCH_END EQU $ - 2
; CODE AREA
; ---------
MAIN PROC NEAR
CLD ;All string operations forward.
MOV BX,1024 ;Allocate 1024 paragraphs; 16K.
MOV AH,4AH
INT 21H
MOV DX,OFFSET NOT_ENOUGH ;Exit with message if not enough.
JC ERROR_MSG
MOV AX,500H ;Make sure zero video page.
INT 10H
MOV AX,40H ;Point to BIOS data area.
MOV ES,AX
MOV AX,1A00H ;Get display info.
INT 10H
CMP AL,1AH ;Function supported?
JNZ CK_EGA ;If no, not VGA; check EGA.
CMP BL,7 ;Else, monochrome VGA?
JZ GET_CRT_MODE ;If yes, OK.
CMP BL,8 ;Else, color VGA?
JZ GET_CRT_MODE ;If yes, OK.
CK_EGA: MOV MAX_LINES,14 ;Else, use 14 max lines for EGA.
MOV BL,10H ;Get EGA information.
MOV AH,12H
INT 10H
MOV DX,OFFSET NOT_EGA_VGA
CMP BL,10H ;Is there an EGA?
JZ ERROR_MSG ;If no, exit with message.
TEST ES:BYTE PTR [87H],8 ;Is EGA active?
JNZ ERROR_MSG ;If no, exit with message.
GET_CRT_MODE: MOV BL,ES:[49H] ;Retrieve CRT_MODE.
CALL INFORMATION ;Get font information.
MOV DX,OFFSET NOT_SUPPORTED
CMP CX,MAX_POINTS ;Font greater than 16 points?
JBE CK_MODE ;If no, OK.
ERROR_MSG: CALL PRINT_STRING ;Print error message.
ERROR_EXIT: MOV AL,1 ;ERRORLEVEL = 1
JMP TERMINATE ;Exit.
CK_MODE: CMP BL,7 ;CRT_MODE mono?
JZ SAVE_MODE ;If yes, skip.
MOV BYTE PTR PROTECT_A000H + 7,0EH ;Else, change parameter.
CMP BL,2 ;Is mode BW80?
JZ SAVE_MODE ;If yes, defaults.
MOV ATTRIBUTE,17H ;Else, use color attributes.
MOV INVERSE,71H
CMP BL,3 ;Are we in CO80?
JZ SAVE_MODE ;If yes, done here.
MOV AX,3 ;Else, change to CO80.
INT 10H
MOV BL,3
SAVE_MODE: MOV CRT_MODE,BL ;Save CRT_MODE in loader.
CALL SETUP ;Setup the display.
;************************** MAIN LOOP **************************;
; User input dispatcher. AH = ASCII character; AL = Scan Code. ;
;***************************************************************;
INPUT: CALL HIDE_CURSOR ;Park cursor off screen.
CALL GET_INPUT ;Get some input from user.
CMP BUTTONS,0 ;Was a mouse button pressed?
JZ CK_ASCII ;If no, check keyboard input.
CALL BUTTON_PRESS ;Else, process button press.
JMP SHORT INPUT ;Next input.
CK_ASCII: OR AL,AL ;Scan code zero?
JZ ALT_INPUT ;If yes, ALT keypad entry.
MOV DI,OFFSET DISPATCH_KEY ;Else, check dispatch table.
MOV CX,DISPATCH_CNT
REPNZ SCASB
JNZ ALT_INPUT ;If no match, keyboard char.
SHL CX,1 ;Else, look up subroutine
MOV DI,OFFSET DISPATCH_END
SUB DI,CX
CALL [DI] ; and process command.
JMP SHORT INPUT ;Next input.
ALT_INPUT: OR AH,AH ;ASCII zero?
JZ INPUT ;If yes, skip.
MOV EDIT_CHAR,AH ;Else, store as new character.
CALL SETUP_END ;Display new edit character.
JMP SHORT INPUT ;Next input.
;---------------------------------------------------;
; Exit. If font was modified, prompt user to save. ;
;---------------------------------------------------;
EXIT: CALL CLS ;Clear the screen.
CMP MODIFY_FLAG,1 ;Font modified?
JNZ GOOD_EXIT ;If no, return to DOS.
MOV SI,OFFSET FILE_MSG
CMP FILE_FLAG,1 ;If there a filename?
JZ DO_FILE ;If yes, display it.
MOV FILENAME,SI ;Else, display "file".
DO_FILE: MOV SI,OFFSET SAVE_MSG
CALL PROMPT ;Prompt user to save.
JNZ GOOD_EXIT ;If "Y"es not pressed, exit.
CMP FILE_FLAG,1 ;Else, is there a filename?
JZ DO_SAVE ;If yes, save it.
CALL GET_NAME ;Else, get a filename.
JC GOOD_EXIT ;If aborted, exit.
DO_SAVE: CALL SAVE_FILE ;Save the font COM file.
GOOD_EXIT: CALL CLS ;Clear the screen.
XOR AL,AL ;ERRORLEVEL zero.
TERMINATE: MOV AH,4CH ;Return to DOS.
INT 21H
MAIN ENDP
; ***************
; * SUBROUTINES *
; ***************
;-------------------------------------------------------------;
; What follows is the user input command processing routines. ;
;-------------------------------------------------------------;
BUTTON_PRESS: CALL GET_CURSOR ;Is cursor in character box?
JNZ DO_ENTER ;If yes, process as if Enter.
CMP LEFT_BUTTON,0 ;Else, left button press
JZ TURN_OFF ; will turn on pixel.
CALL GET_PIXEL ;Get the pixel.
OR [DI],AH ;Turn it on.
JMP SHORT BUTTON_END
TURN_OFF: CALL GET_PIXEL ;Right button will turn off pixel
XOR AH,0FFH ;Invert bit mask.
AND [DI],AH ;Turn it off.
BUTTON_END: CALL UPDATE_CURSOR ;Update the cursor.
CALL LOAD_CHAR ;Load the character.
RET
;--------------------------------;
ENTER: CALL GET_CURSOR ;Is cursor in character box?
JZ ENTER_END ;If no, ignore.
DO_ENTER: CALL GET_CHAR ;Else, get the highlighted char.
MOV EDIT_CHAR,AL ;Store it as new edit char.
CALL NEW_CHAR ;Display the edit character.
ENTER_END: RET
;--------------------------------;
LEFT: MOV BP,0FFH ;Movement = 0 rows; -1 cols.
JMP SHORT ARROWS
RIGHT: MOV BP,1 ;Movement = 0 rows; +1 cols.
JMP SHORT ARROWS
UP: MOV BP,0FF00H ;Movement = -1 rows; 0 cols.
JMP SHORT ARROWS
DOWN: MOV BP,100H ;Movement = +1 rows; 0 cols.
ARROWS: CALL RESTORE ;Restore current cursor position.
CALL GET_CURSOR ;Cursor in edit box?
MOV CX,BP
JNZ CHAR_ARROW ;If no, do character movement.
ADD CL,CL ;Else, double up col. movement.
CALL CK_BOUNDS ;Move cursor; check the boundary.
SUB AX,EDIT_TOP ;AX has position; make relative.
MOV EDIT_CURSOR,AX ;Store as new edit cursor.
MOV BH,LAST_PIXEL ;Retrieve the last pixel.
CALL GET_PIXEL ;Get pixel in new position.
CMP SHIFT_STATE,0 ;Button or Shift key depressed?
JZ UPDATE_PIXEL2 ;If no, update new cursor pos.
OR BH,BH ;Else, was last pixel on?
JNZ BIT_ON ;If yes, drag to new position.
XOR AH,0FFH ;Else, invert mask
AND BYTE PTR [DI],AH; ; and drag pixel off.
JMP SHORT UPDATE_PIXEL1
BIT_ON: OR BYTE PTR [DI],AH ;Turn the pixel on.
UPDATE_PIXEL1: CALL LOAD_CHAR ;Load the character.
UPDATE_PIXEL2: CALL UPDATE_CURSOR ;Update the cursor display.
RET
;--------------------------------;
CHAR_ARROW: CALL CK_BOUNDS ;Move cursor; check the boundary.
SUB AX,CHAR_TOP ;Convert to relative position.
MOV CHAR_CURSOR,AX ;Store new character box pos.
CMP SHIFT_STATE,0 ;Button or Shift key depressed?
JZ CHAR_END ;If no, done here.
NEW_CHAR: CALL GET_CHAR ;Else, get the character
MOV EDIT_CHAR,AL ; and use as new edit character.
CALL DISPLAY_FONT ;Display it.
CHAR_END: CALL UPDATE_CURSOR ;Update the cursor display.
RET
;--------------------------------;
PGUP: DEC EDIT_CHAR ;Next lower edit character.
JMP SHORT PAGE_END
PGDN: INC EDIT_CHAR ;Next higher edit character.
PAGE_END: CALL SETUP_END ;Display it.
RET
;--------------------------------;
TAB: CALL RESTORE ;Restore current cursor position.
XOR EDIT_FLAG,1 ;Toggle Edit/char active box.
CALL UPDATE_CURSOR ;Display cursor in new box.
RET
;--------------------------------;
SPACE_BAR: CALL GET_CURSOR ;Is cursor in character box?
JNZ SPACE_END ;If yes, ignore.
CALL GET_PIXEL ;Else, get the pixel.
XOR [DI],AH ;Toggle the pixel.
CALL UPDATE_PIXEL1 ;Update character and cursor.
SPACE_END: RET
;--------------------------------;
DEL_ROW: CALL GET_CURSOR ;Is cursor in character box?
JNZ DELETE_RETURN ;If yes, ignore.
MOV BP,POINTS ;Else, retrieve scan line points.
CMP BP,1 ;Is there only one scan line?
JZ DELETE_RETURN ;If yes, ignore.
MOV AL,AH ;Else, delete position equals
XOR AH,AH ; POINTS - relative ROW.
SUB BP,AX
CALL CLEAR_MENU ;Clear part of the menu and
MOV DX,OFFSET WARNING_MSG ; display warning message.
CALL PRINT_STRING
CALL QUERY ;Should we delete?
JNZ DELETE_END ;If no, done here.
MOV BX,POINTS ;Else, retrieve bytes/char.
MOV SI,OFFSET EDIT_FONT ;Delete edit font.
CALL DELETE
MOV SI,OFFSET TEMPLATE_FONT ;Do same to template font.
CALL DELETE
DEC BX ;One less byte/char.
MOV BH,BL
CMP BYTE PTR EDIT_CURSOR + 1,BL ;Was last row deleted?
JNZ LOAD_IT ;If no, OK.
DEC BL ;Else, move cursor up one
MOV BYTE PTR EDIT_CURSOR + 1,BL ; row so it's on new char.
LOAD_IT: MOV BP,OFFSET EDIT_FONT
CALL USER_LOAD ;Load the new font.
CALL INFORMATION ;Get font information.
MOV MODIFY_FLAG,1 ;Note that font's been modified.
CALL CLS ;Clear the old display.
DELETE_END: XOR DX,DX
CALL SET_CURSOR
CALL DISPLAY_COPY ;Display new font.
DELETE_RETURN: RET
;-----------------;
DELETE: MOV DI,SI ;Destination starts at source.
MOV CX,256 ;256 characters to do.
NEXT_DELETE: PUSH CX ;Save character count.
MOV CX,BX ;BX has bytes/character.
CK_SKIP: CMP CX,BP ;Is this the row to delete?
JZ SKIP_ROW ;If yes, skip it.
MOVSB ;Else, move it down.
JMP SHORT LOOP_DELETE
SKIP_ROW: INC SI ;Skip deletion row.
LOOP_DELETE: LOOP CK_SKIP ;Do all character rows.
POP CX
LOOP NEXT_DELETE ;Do all 256 characters.
RET
;--------------------------------;
INS_ROW: XOR BL,BL ;Insert a zero byte.
JMP SHORT INS_EDIT
;--------------------------------;
DUP_ROW: MOV BL,-1 ;Insert a duplicate byte.
INS_EDIT: CALL GET_CURSOR ;Is cursor in character box?
JNZ INSERT_END ;If yes, ignore.
MOV BH,AH ;Row to be inserted.
INC BH ;Adjust.
MOV BP,POINTS ;Retrieve bytes/char.
CMP BP,MAX_LINES ;Character maxed out?
JZ INSERT_END ;If yes, done here.
STD ;Else, backward moves.
MOV SI,OFFSET EDIT_FONT ;Insert a row.
CALL INSERT
MOV SI,OFFSET TEMPLATE_FONT ;Do same to template font.
CALL INSERT
CLD ;String operation back forward.
MOV BX,BP ;Increment bytes/character.
MOV BH,BL
INC BH
MOV BP,OFFSET EDIT_FONT ;Load the new font.
CALL USER_LOAD
CALL INFORMATION ;Get font information.
MOV MODIFY_FLAG,1 ;Note that font's been modified.
CALL SETUP_END ;Display new font.
INSERT_END: RET
;-----------------;
INSERT: MOV AX,BP ;Go to end of font
MOV CX,256 ; (256 * points) - 1
MUL CX
DEC AX
ADD SI,AX
MOV DI,SI
ADD DI,CX ;New font = old font + 256.
NEXT_INSERT: PUSH CX ;Save character count.
MOV CX,BP ;Retrieve bytes/char.
MOVE_BYTE: MOVSB ;Move a byte.
CMP CL,BH ;Is there an insert row?
JNZ LOOP_INSERT
MOV AL,BL ;If yes, assume zero insert.
OR BL,BL ;Is zero to be inserted?
JZ INSERT_IT ;If yes, guessed right.
MOV AL,[SI+1] ;Else, duplicate with byte below.
INSERT_IT: STOSB ;Insert it.
LOOP_INSERT: LOOP MOVE_BYTE ;Do all bytes/char.
POP CX
LOOP NEXT_INSERT ;Do all 256 characters.
RET
;--------------------------------;
COPY_TEMP: CALL GET_PIXEL ;Get index to current char.
MOV DI,SI ;Destination = Source+(16 * 256).
ADD SI,MAX_POINTS * 256
MOV CX,POINTS ;Bytes/character to copy.
REP MOVSB ;Copy them.
CALL SETUP_END ;Update the display.
CALL LOAD_CHAR ;Load the new character.
RET
;--------------------------------;
SAVE: CMP FILE_FLAG,1 ;Is there a filename?
JZ SAVE_IT ;If yes, save it.
CALL CLS ;Else, clear screen.
CALL GET_NAME ;Get a filename.
PUSHF ;Save results.
CALL DISPLAY_HEAD ;Redisplay menu.
POPF ;Retrieve results.
JC SAVE_END ;If user aborted, skip save.
SAVE_IT: CALL SAVE_FILE ;Save the file.
SAVE_END: RET
;*********** END OF COMMAND PROCESSING ROUTINES ***********;
;---------------------------;
; OUTPUT ;
; If Edit cursor, ZF = 1 ;
; If Char cursor, ZF = 0 ;
; DX = cursor position. ;
; AX = relative position. ;
;---------------------------;
GET_CURSOR: MOV AX,EDIT_CURSOR ;Assume edit cursor; retrieve it.
MOV DX,AX ;Cursor position = relative
ADD DX,EDIT_TOP ; position + top left of edit box
CMP EDIT_FLAG,1 ;Are we in edit box?
JZ CURSOR_END ;If yes, guessed right.
MOV AX,CHAR_CURSOR ;Else, retrieve char. cursor.
MOV DX,AX ;Calculate cursor position.
ADD DX,CHAR_TOP
CURSOR_END: RET
;---------------------------------------------------;
; Return highlighted cursor position to background. ;
;---------------------------------------------------;
RESTORE: MOV BL,ATTRIBUTE ;Background attribute.
CALL GET_CURSOR ;Is cursor in character box?
JNZ CHAR_RESTORE ;If yes, restore char box.
CALL GET_PIXEL ;Else, get pixel and write.
CALL WRITE_PIXEL
RET
CHAR_RESTORE: CALL GET_CHAR ;Get character and write.
CALL WRITE_CHAR
RET
;--------------------------------;
; Highlight new cursor position. ;
;--------------------------------;
UPDATE_CURSOR: MOV BL,ATTRIBUTE ;Retrieve background attribute.
OR BL,INTENSITY ;Turn on intensity bit.
CALL GET_CURSOR ;Is cursor in character box?
JNZ DO_CHAR ;If yes, do character cursor.
FONT_CURSOR: CALL GET_PIXEL ;Else, get pixel and write it.
CALL WRITE_PIXEL
RET
DO_CHAR: CALL GET_CHAR ;Retrieve character.
MOV DI,OFFSET BLANKS ;Use inverse video for invisible
MOV CX,3 ; characters 0, 32 and 255.
REPNZ SCASB
JNZ DO_CURSOR
MOV BL,INVERSE
DO_CURSOR: CALL WRITE_CHAR ;Update the character cursor.
RET
;-----------------------------------;
; INPUT ;
; AX = Relative cursor position. ;
; DX = Actual cursor position. ;
; CX = Direction. ;
; ;
; OUTPUT ;
; DX = New cursor position. ;
; AX = New cursor position. ;
; BX preserved. ;
;-----------------------------------;
CK_BOUNDS: ADD DH,CH ;Add row direction
ADD DL,CL ; and column direction.
PUSH BX ;Save BX.
MOV BL,16 ;Use 16 as bounds for char.
CMP EDIT_FLAG,1 ; box bottom.
JNZ CK_LEFT ;Use bytes/char bounds for edit
MOV BX,POINTS ; box bottom.
CK_LEFT: ADD AL,CL ;Add column to relative pos.
JGE CK_RIGHT
ADD DL,16 ;If too far left,
JMP SHORT BOUNDS_END ; wrap to right.
CK_RIGHT: CMP AL,16 ;If too far right,
JB CK_UP
SUB DL,16 ; wrap to left.
CK_UP: ADD AH,CH ;Add row to relative position.
JGE CK_DOWN
ADD DH,BL ;If too far up,
JMP SHORT BOUNDS_END ; wrap to bottom
CK_DOWN: CMP AH,BL ;If too far down,
JB BOUNDS_END ; wrap to top.
MOV DH,EDIT_ROW
BOUNDS_END: MOV AX,DX ;Return copy of cursor position.
POP BX ;Restore BX.
RET
;----------------------------------;
; INPUT ;
; AX = Relative cursor position. ;
; ;
; OUTPUT ;
; AL = character. ;
;----------------------------------;
GET_CHAR: MOV CL,4 ;Character = row * 16 + column.
SHL AH,CL
ADD AL,AH
RET
;-------------------;
; Font information. ;
;-------------------;
INFORMATION: MOV BH,2 ;Get information.
MOV AX,1130H
INT 10H
PUSH CS ;Restore extra segment.
POP ES
MOV POINTS,CX ;Store bytes/character.
MOV ROWS,DL ;Store rows on screen.
RET
;----------------------------------------------------------------;
; Filename is parsed of white space and COM extension tacked on. ;
;----------------------------------------------------------------;
PARSE_FILE: MOV SI,81H ;Point to parameter.
NEXT_PARSE: LODSB ;Get a byte.
CMP AL,SPACE ;Is it leading space?
JZ NEXT_PARSE ;If yes, ignore.
CMP AL,TAB_CHAR ;Is it leading tab?
JZ NEXT_PARSE ;If yes, ignore.
DEC SI ;Adjust pointer.
MOV FILENAME,SI ;Store start of filename.
FIND_END: LODSB ;Get a byte.
CMP AL,SPACE ;Is it space or below?
JBE PARSE_END ;If yes, end of filename.
CMP AL,"a" ;Capitalize.
JB CK_DOT
CMP AL,"z"
JA CK_DOT
AND BYTE PTR [SI-1],5FH
CK_DOT: CMP AL,"." ;Is it a dot?
JNZ FIND_END ;If no, continue.
PARSE_END: MOV DI,SI ;Else, if dot or end of filename
DEC DI ; tack on ".COM".
MOV SI,OFFSET COM
MOV CX,5
REP MOVSB
RET
;-----------------------------;
; OUTPUT ;
; If file exists, CY = 0 ;
; If file not found, CY = 1 ;
;-----------------------------;
OPEN_FILE: MOV DX,FILENAME
MOV AX,3D02H ;Open file for reading, writing.
INT 21H
SAVE_HANDLE: MOV FILE_HANDLE,AX ;Save filehandle.
MOV BX,AX
RET
;------------------------;
; OUTPUT ;
; If successful CY = 0 ;
; If failed CY = 1 ;
;------------------------;
CREATE_FILE: MOV DX,FILENAME
XOR CX,CX ;Create normal file.
MOV AH,3CH
INT 21H
JC CREATE_END
CALL SAVE_HANDLE ;If successful, save filehandle
CALL SAVE_FILE ; and save font file.
CREATE_END: RET
;-----------------------------------------------------------------------;
; Read the parsed file. Check if legitimate font file. Load the font. ;
;-----------------------------------------------------------------------;
READ_FILE: MOV BX,FILE_HANDLE ;Retrieve filehandle.
MOV DX,OFFSET LOADER ;Point to loader.
MOV CX,LOADER_LENGTH ;Bytes to read.
MOV AH,3FH ;Read from disk.
INT 21H
MOV SI,OFFSET PROGRAMMER1 ;Use name as legitimate font
MOV DI,OFFSET PROGRAMMER2 ; file signature.
MOV CX,SIGNATURE_LEN / 2
REPZ CMPSW
JZ READ_END
CALL DISP_FILENAME
MOV DX,OFFSET NOT_FONT_MSG ;If not font file, exit
JMP ERROR_MSG ; with message.
READ_END: MOV FILE_FLAG,1 ;Else, note that filename found.
PUSH BX ;Save filehandle.
MOV BP,OFFSET EDIT_FONT ;Point to font.
MOV BH,BYTE PTR POINTS ;Bytes/character.
CALL USER_LOAD ;Load the font.
CALL INFORMATION ;Get font information.
POP BX ;Retrieve filehandle.
;--------------------------------;
CLOSE_FILE: MOV AH,3EH
INT 21H
RET
;--------------------------------;
SAVE_FILE: CALL OPEN_FILE ;Open the file and write
MOV DX,OFFSET LOADER ; font image and loader to disk.
MOV CX,LOADER_LENGTH
MOV AH,40H
INT 21H
MOV MODIFY_FLAG,0 ;Reset modify flag.
MOV FILE_FLAG,1 ;Note that have a filename.
JMP SHORT CLOSE_FILE
;-------------------------------;
; INPUT ;
; SI = first string to write. ;
; ;
; OUTPUT ;
; If "Y"es pressed, ZF = 1 ;
; Else, ZF = 0 ;
;-------------------------------;
PROMPT: CALL TTY_STRING ;Write preface string.
CALL DISP_FILENAME ;Write filename.
QUERY: MOV SI,OFFSET YES_NO ;Write query string.
CALL TTY_STRING
CALL GET_KEY ;Get a response.
CMP AH,Y_SCAN ;Check if "Y" pressed.
RET
;-------------------------------;
; OUTPUT ;
; If name valid, CY = 0 ;
; If invalid or abort, CY = 1 ;
;-------------------------------;
GET_NAME: MOV DX,OFFSET FILENAME_MSG ;Ask for filename.
CALL PRINT_STRING
MOV DI,81H ;Use PSP's DTA for input.
NEXT_NAME: CALL GET_KEY ;Get a keystroke.
CMP AH,ESC_SCAN ;Esc?
STC
JZ NAME_END ;If yes, abort with CY = 1.
CMP AH,LEFT_ARROW ;Backspace with left arrow
JZ DO_BS ; or backspace key.
CMP AH,BS_SCAN
JZ DO_BS
CMP AH,ENTER_SCAN ;If Enter key, done here.
JZ STORE_BYTE
CMP AL,SPACE ;Ignore space and below.
JBE NEXT_NAME
JMP SHORT STORE_BYTE
DO_BS: DEC DI ;TTY Backspace = the characters
MOV AL,8 ; 8, space and 8.
PUSH AX
CALL WRITE_TTY
MOV AL,SPACE
CALL WRITE_TTY
POP AX
JMP SHORT DISPLAY_BYTE
STORE_BYTE: STOSB
CMP AH,ENTER_SCAN ;Done if Enter.
JZ PARSE_IT
DISPLAY_BYTE: CALL WRITE_TTY ;Echo input to screen.
JMP SHORT NEXT_NAME
PARSE_IT: CALL PARSE_FILE ;Parse the filename.
CALL OPEN_FILE ;See if it exists.
JC CREATE_IT ;If no, create it.
MOV SI,OFFSET EXIST_MSG ;Else, ask if should write
CALL PROMPT ; over existing file.
JNZ GET_NAME
CREATE_IT: CALL CREATE_FILE ;Create the file.
JNC NAME_END
MOV DX,OFFSET FAILED_MSG ;If failed, inform user
CALL PRINT_STRING ; and ask for new filename.
JMP SHORT GET_NAME
NAME_END: RET
;--------------------------------------;
; OUTPUT ;
; AH = Bit mask ;
; AL = PIXEL_ON or PIXEL_OFF ;
; SI = Pointer to start of Character ;
; DI = Pointer to start of Scan Line ;
; PIXEL = 0 or -1 ;
;--------------------------------------;
GET_PIXEL: MOV SI,OFFSET EDIT_FONT ;Point to start of edit font.
CALL CHAR_START ;Index to current character.
MOV DI,SI ;Also into DI.
MOV CX,EDIT_CURSOR ;Retrieve edit cursor.
SHR CL,1 ;Two col/bit so divide by two.
MOV AH,10000000B ;Bit starts in most significant.
SHR AH,CL ;Shift bit to column position.
MOV CL,CH ;Row in CL.
XOR CH,CH ;Zero in high half.
ADD DI,CX ;Add to character start.
MOV CL,[DI] ;Retrieve the current byte.
MOV AL,PIXEL_OFF ;Assume it is off.
MOV LAST_PIXEL,0
AND CL,AH ;AND with bit mask.
JZ END_PIXEL ;If off, guessed right.
MOV AL,PIXEL_ON ;Else, pixel is on.
MOV LAST_PIXEL,-1
END_PIXEL: RET
;--------------------------------;
WRITE_PIXEL: CALL WRITE_CHAR ;Two characters/pixel.
INC DL
CALL WRITE_CHAR
INC DL
RET
;----------------------------;
; INPUT ;
; SI = Font start. ;
; ;
; OUTPUT ;
; AX = Edit character. ;
; SI = Start of character. ;
;----------------------------;
CHAR_START: MOV CX,POINTS ;Retrieve bytes/character.
MOV AL,EDIT_CHAR ;Retrieve edit character.
XOR AH,AH ;Zero in high half.
PUSH AX ;Preserve character.
MUL CL ;Char start = bytes/char * char.
ADD SI,AX ;Add to index.
POP AX ;Retrieve character.
RET
;--------------------------------------------;
; OUTPUT ;
; AH = ASCII character. ;
; AL = Scan code. ;
; BUTTONS = button pressed. ;
; SHIFT_STATE = Shift or button depressed. ;
;--------------------------------------------;
GET_INPUT: XOR BP,BP ;Store input in BP; start with 0.
MOV SHIFT_STATE,0 ;Zero in Shift state.
MOV BUTTONS,0 ;Zero in Buttons also.
CMP MOUSE_FLAG,1 ;Is the mouse active?
JNZ CK_KEYBOARD ;If no, skip mouse poll.
XOR BX,BX ;Left button.
MOV AX,5 ;Button press information.
INT 33H
OR SHIFT_STATE,AL ;Store button depressed info.
OR LEFT_BUTTON,BL ;Store button press info.
MOV BX,1 ;Do same for right button.
MOV AX,5
INT 33H
OR RIGHT_BUTTON,BL ;Store button pressed info.
CMP BUTTONS,0 ;Any button pressed?
JNZ INPUT_END ;If yes, done here.
MOUSE_MOTION: MOV AX,0BH ;Read mouse motion.
INT 33H
ADD CX,HORIZONTAL ;Add in last horizontal motion.
ADD DX,VERTICAL ; and last vertical motion.
MOV AX,MICKEY ;Retrieve mouse unit of motion.
MOV SI,RIGHT_ARROW ;Assume right movement.
CMP CX,AX ;Is horizontal > mickey?
JG HORIZ ;If yes, guessed right.
MOV SI,DN_ARROW ;Assume down movement.
CMP DX,AX ;Is vertical > mickey?
JG VERT ;if yes, guessed right.
NEG AX ;Else, negate mickey.
MOV SI,LEFT_ARROW ;Assume left movement.
CMP CX,AX ;Is horizontal < mickey?
JL HORIZ ;If yes, guessed right.
MOV SI,UP_ARROW ;Assume up movement.
CMP DX,AX ;Is vertical < mickey?
JGE STORE_MOTION ;If yes, guessed right.
VERT: SUB DX,AX ;Subtract vertical mickey.
JMP SHORT STORE_SCAN ;Update vertical.
HORIZ: SUB CX,AX ;Subtract horizontal mickey.
STORE_SCAN: MOV BP,SI ;Store scan code in BP.
STORE_MOTION: MOV HORIZONTAL,CX ;Update movements.
MOV VERTICAL,DX
CK_KEYBOARD: MOV AH,2 ;Keyboard Shift state.
INT 16H
AND AL,SHIFT_KEYS ;Mask off all but Shift keys.
OR SHIFT_STATE,AL ;Store Shift state.
MOV AH,1 ;Keystroke status.
INT 16H
JZ STORE_INPUT ;If none available, done here.
CALL GET_KEY ;Else, get keystroke
XCHG AL,AH ;Exchange scan/ASCII code.
JMP SHORT INPUT_END
STORE_INPUT: MOV AX,BP ;Return input in AX
OR AX,AX ;Is there input?
JNZ INPUT_END ;If yes, done here.
CMP BUTTONS,0 ;Is there button pressed?
JNZ INPUT_END ;If yes, done here.
JMP GET_INPUT ;Else, wait until input.
INPUT_END: RET
;--------------------------------;
DISPLAY_FONT: MOV AL,ROWS ;Retrieve rows on screen.
INC AL ;Zero based; adjust.
MOV DX,34EH ;Display at Row 2; Col. 77.
MOV CX,3 ;Three bytes to write.
MOV BL,ATTRIBUTE ;Use background attribute.
CALL DIVIDE ;Display the number.
MOV DX,BOX_TOP + 103H ;Point to inside of info box.
MOV AL,EDIT_CHAR ;Retrieve character.
CALL WRITE_CHAR ;Display it.
ADD DL,7 ;Move to end of number col.
MOV CX,3 ;Three bytes to write.
CALL DIVIDE ;Display the number.
MOV BP,TEMPLATE_TOP ;Display template character.
MOV SI,OFFSET TEMPLATE_FONT
CALL UPDATE_FONT
MOV BP,EDIT_TOP ;Display edit character.
MOV SI,OFFSET EDIT_FONT
UPDATE_FONT: CALL CHAR_START ;Retrieve index to character.
NEXT_LINE: LODSB ;Get a byte.
MOV AH,AL ;Store in AH.
MOV DI,AX ;Store in DI.
PUSH CX ;Preserve bytes/char.
MOV CX,8 ;Eight bits/byte.
MOV DX,BP ;Top left of font display.
NEXT_PIXEL: RCL DI,1 ;Get a bit.
MOV AL,PIXEL_ON ;Assume it's on.
JC DISPLAY_IT ;Did bit end up in carry flag?
MOV AL,PIXEL_OFF ;If no, guessed wrong; pixel off.
DISPLAY_IT: CALL WRITE_PIXEL ;Display the pixel.
LOOP NEXT_PIXEL ;Do all 8 pixels.
ADD BP,100H ;Next display row.
POP CX ;Retrieve bytes/char.
LOOP NEXT_LINE ;Do all rows.
RET
;---------------------------;
; INPUT ;
; Entry point = DIVIDE. ;
; AL = Number to display. ;
; BL = Attribute. ;
; CX = Places to display. ;
; DX = Cursor position. ;
;---------------------------;
NEXT_COUNT: MOV AH,SPACE ;Assume zero.
OR AL,AL ;Is it a zero?
JZ ASCII ;If yes, display space instead.
DIVIDE: MOV BH,10 ;Divisor of ten.
XOR AH,AH ;Zero in high half.
DIV BH ;Divide by ten.
ADD AH,"0" ;Convert to ASCII.
ASCII: XCHG AL,AH ;Remainder in AL.
CALL WRITE_CHAR ;Display it.
XCHG AL,AH ;Back to AH.
DEC DL ;Move back one column.
LOOP NEXT_COUNT ;Display all three bytes.
RET
;---------------------;
; INPUT ;
; AL = Character ;
; BL = Attribute ;
; AX, CX preserved. ;
;---------------------;
WRITE_CHAR: PUSH AX
PUSH CX
CALL SET_CURSOR
MOV CX,1
MOV AH,9 ;Write attribute/character.
INT 10H
POP CX
POP AX
RET
;------------------------------------------------------------------------------;
; The Ega/Vga registers are programmed to access segment A000h where the ;
; fonts are stored. The font is retrieved and registers reset back to normal. ;
;------------------------------------------------------------------------------;
RETRIEVE_FONT: MOV SI,OFFSET ACCESS_A000H ;Point to access parameters.
CALL SET_REGISTERS ;Set the registers.
MOV BX,POINTS ;Retrieve bytes/character.
MOV AX,0A000H ;Point to font segment.
MOV DS,AX
MOV DI,OFFSET EDIT_FONT ;Point to destination.
MOV BP,256 ;256 characters.
XOR DX,DX ;Source starting offset of zero.
NEXT_CHAR: MOV SI,DX ;Point to source.
MOV CX,BX ;Bytes/character.
REP MOVSB ;Retrieve the bytes.
ADD DX,20H ;Next character two paragraphs.
DEC BP ;Do all 256 characters.
JNZ NEXT_CHAR
PUSH CS ;Restore data segment.
POP DS
MOV SI,OFFSET EDIT_FONT ;Copy the edit font to template.
MOV DI,OFFSET TEMPLATE_FONT
MOV CX,MAX_POINTS * 256 / 2
REP MOVSW
MOV SI,OFFSET PROTECT_A000H ;Point to normal parameters.
SET_REGISTERS: MOV CX,2 ;Two sequencer registers.
MOV DX,3C4H ;Indexing register.
CALL NEXT_REGISTER
MOV CX,3 ;Three graphics controller regs.
MOV DL,0CEH ;Indexing registers.
NEXT_REGISTER: LODSB ;Get index.
OUT DX,AL
INC DX
LODSB ;Get value.
OUT DX,AL
DEC DX
LOOP NEXT_REGISTER
RET
;-----------------------------------------------------;
; Similar to RETRIEVE_FONT procedure except character ;
; is uploaded instead of entire font down loaded. ;
;-----------------------------------------------------;
LOAD_CHAR: MOV SI,OFFSET ACCESS_A000H
CLI
CALL SET_REGISTERS
MOV SI,OFFSET EDIT_FONT ;Point to character
CALL CHAR_START ; to upload.
PUSH CX ;Preserve bytes/char.
MOV CL,5 ;32 bytes record for A000h font.
SHL AX,CL ;Index to appropriate character.
MOV DI,AX
POP CX
MOV AX,0A000H ;Point to font segment.
MOV ES,AX
REP MOVSB ;Upload the bytes.
PUSH CS ;Restore extra segment.
POP ES
MOV SI,OFFSET PROTECT_A000H
CALL SET_REGISTERS
STI
MOV MODIFY_FLAG,1 ;Note that font modified.
RET
;--------------------------------;
SET_CURSOR: PUSH AX
XOR BH,BH
MOV AH,2 ;Set cursor position.
INT 10H
POP AX
RET
;--------------------------------;
HIDE_CURSOR: MOV DH,ROWS
INC DH
XOR DL,DL ;Hide cursor one row below
CALL SET_CURSOR ; displayable rows.
RET
;--------------------------------;
CLEAR_MENU: MOV CX,100H ;Row 1; column zero.
MOV DX,34FH ;Row 3; column 79.
JMP SHORT SCROLL
CLS: XOR CX,CX ;Row zero; column zero.
MOV DH,ROWS ;Rows.
MOV DL,79 ;Column 79.
SCROLL: MOV BH,7 ;Attribute.
MOV AX,600H ;Scroll window of active page.
INT 10H
XOR DX,DX
CALL SET_CURSOR
RET
;--------------------------------;
GET_KEY: XOR AH,AH
INT 16H
RET
;--------------------------------;
PRINT_STRING: MOV AH,9
INT 21H
RET
;--------------------------------;
DISP_FILENAME: MOV SI,FILENAME
JMP SHORT TTY_STRING
;-----------------;
DO_WRITE: CALL WRITE_TTY
TTY_STRING: LODSB
OR AL,AL
JNZ DO_WRITE
RET
;-----------------;
WRITE_TTY: MOV AH,0EH
INT 10H
RET
;--------------------------------;
DO_CHAR_ATTR: CALL WRITE_CHAR
INC DL
CHAR_ATTRIB: LODSB
OR AL,AL
JNZ DO_CHAR_ATTR
RET
;--------------------------------;
SETUP: CLI ;No interrupts.
CALL RETRIEVE_FONT ;Retrieve font.
STI ;Interrupts back on.
CMP BYTE PTR DS:[80H],0 ;Command line parameter?
JZ CK_MOUSE ;If no, skip to mouse.
CALL PARSE_FILE ;Else, parse the parameter.
CALL OPEN_FILE ;Try to open the file.
JC CREATE_PROMPT ;If not found, ask to create.
CALL READ_FILE ;Else, read the file.
JMP SHORT CK_MOUSE ;Done here.
CREATE_PROMPT: MOV SI,OFFSET CREATE_MSG ;Display create query.
CALL PROMPT
JZ CREATE ;If got thumbs up, create it.
JMP ERROR_EXIT ;Else, exit.
CREATE: CALL CREATE_FILE ;Create the file.
MOV DX,OFFSET FAILED_MSG ;If failed, exit with message.
JNC CK_MOUSE
JMP ERROR_MSG
CK_MOUSE: XOR AX,AX ;Mouse reset and status.
INT 33H
OR AX,AX ;Is mouse active?
JZ DISPLAY_HEAD ;If no, skip.
MOV MOUSE_FLAG,1 ;Else, flag.
DISPLAY_HEAD: CALL CLS ;Clear the screen.
DISPLAY_COPY: MOV SI,OFFSET COPYRIGHT ;Display copyright in
MOV BL,INVERSE ; inverse video.
CALL CHAR_ATTRIB
MOV DX,100H ;Row 1; column 0.
CALL SET_CURSOR
MOV DX,OFFSET MENU ;Display menu.
CALL PRINT_STRING
CMP FILE_FLAG,1 ;If filename, display it.
JNZ DISPLAY_MENU
CALL DISP_FILENAME
DISPLAY_MENU: MOV DX,200H ;Row 2; column 0.
CALL SET_CURSOR
MOV DX,OFFSET MENU1 ;Display more menu.
CALL PRINT_STRING
MOV SI,OFFSET MENU2
MOV BL,NORMAL
MOV DX,436H
CALL CHAR_ATTRIB
MOV DX,536H
CALL CHAR_ATTRIB
MOV DX,636H
CALL CHAR_ATTRIB
MOV SI,OFFSET CAPTIONS ;Display three captions.
MOV CX,3
NEXT_CAPTION: LODSW
MOV DX,AX ;Caption starting cursor pos.
NEXT_CAP: LODSB
CMP AL,0 ;End of string?
JZ END_CAPTION
CALL WRITE_CHAR ;Write the caption.
INC DH ;Next row.
JMP SHORT NEXT_CAP
END_CAPTION: LOOP NEXT_CAPTION ;Do all three captions.
MOV BL,ATTRIBUTE ;Background attribute.
MOV SI,OFFSET CURRENT_BOX ;Display char/ASCII box.
MOV DX,BOX_TOP ;Starting position.
MOV BP,3 ;Three rows.
NEXT_BOX: MOV CX,13 ;13 characters/row.
NEXT_BOX_CHAR: LODSB
CALL WRITE_CHAR
INC DL ;Next column.
LOOP NEXT_BOX_CHAR
MOV DL,LOW BOX_TOP ;Starting column.
INC DH ;Next row.
DEC BP
JNZ NEXT_BOX
MOV DX,CHAR_TOP ;Display character set.
XOR AL,AL ;Start with ASCII zero.
NEXT_SET: MOV CX,16 ;16 bytes/row.
NEXT_BYTE: CALL WRITE_CHAR
INC AL ;Next character.
JZ SETUP_END
INC DL ;Next row.
LOOP NEXT_BYTE
MOV DL,LOW CHAR_TOP ;Starting column.
INC DH
JMP NEXT_SET
SETUP_END: CALL DISPLAY_FONT ;Display the edit and template.
CALL UPDATE_CURSOR ;Display the cursor.
RET
;**************** FONTLOADER ****************;
; This is the code to load the font and ;
; is followed by the edit and template font ;
;********************************************;
LOADER LABEL BYTE
LOADER_OFFSET EQU 100H - LOADER
JMP BEGINNING
; DATA AREA
; ---------
DB CR,SPACE,SPACE,SPACE,CR,LF
PROGRAMMER2 DB " PC Magazine ",BOX," Michael J. Mefford",0,CTRL_Z
SIGNATURE_LEN EQU $ - PROGRAMMER2
CRT_MODE DB ?
EDIT_CURSOR DW 102H
CHAR_CURSOR DW 401H
EDIT_CHAR DB 65
POINTS DW ?
EDIT_FLAG DB 1
; CODE AREA
; ---------
BEGINNING: MOV AX,500H ;Active page zero
INT 10H
MOV AH,0FH ;Current video state.
INT 10H
MOV DI,OFFSET CRT_MODE + LOADER_OFFSET ;Font CRT_MODE.
MOV AH,[DI]
CMP AL,AH ;Same mode?
JZ LOAD_FONT ;If yes, skip.
MOV AL,AH ;Else, change video mode.
XOR AH,AH
INT 10H
LOAD_FONT: MOV BP,OFFSET EDIT_FONT + LOADER_OFFSET
MOV DI,OFFSET POINTS + LOADER_OFFSET
MOV BH,[DI]
USER_LOAD: MOV CX,256
XOR DX,DX
XOR BL,BL
MOV AX,1110H ;User alpha load.
INT 10H
RET ;Terminate.
;--------------------------------;
EVEN
EDIT_FONT LABEL BYTE
TEMPLATE_FONT EQU EDIT_FONT + MAX_POINTS * 256
LOADER_END EQU TEMPLATE_FONT + MAX_POINTS * 256
LOADER_LENGTH EQU LOADER_END - LOADER
_TEXT ENDS
END START